/**************************************************************
 * Project    : Powerbank station TCPSERVER demo
 * Author    : laohuzi
 * Modify    : 2021-10-8
 **************************************************************/
var querystring = require('querystring');
var net = require('net');
var http = require('http');
var url = require('url');
var schedule = require("node-schedule");
var mcfish = require('./mcfish');
var utils = require('./nodejs_util_share.js');
//日志模块
var log4js = require('log4js');
log4js.configure('./log_config.json');
var logger = require('log4js').getLogger("index");


/**************************************************************
 * todo Config your Database
 **************************************************************/
var PoolOption = {
    connectionLimit: 10,
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'monitor_db',
    port: 3306
};

mcfish.init(PoolOption);
// todo Config IP & Port
// Must be the same as the IP & Port set by the factory,(Only support external network, not local area network)
var ip = 'xxx.xxx.xxx.xxx';
var tcpPort = '8188';

// tcp pool
var pool = [];

function Sess() {
    this.sno = '';
    this.auth = false;
    this.socket = null;
}


/**************************************************************
 * HttpServer
 **************************************************************/
// 服务器支持的命令
var reqs = ['borrow', 'open', 'check', 'restart', 'close', 'setting'];

// 创建服务器
var HttpServer = http.createServer();
HttpServer.on("request", function (req, res) {
    // 设置接收数据编码格式为 UTF-8
    req.setEncoding('utf-8');
    var postData = "";
    req.addListener("data", function (postDataChunk) {
        postData += postDataChunk;
    });
    // POST数据接收完毕
    req.addListener("end", function () {
        var request = querystring.parse(postData);
        logger.info(request);
        // 检查参数的合法性
        if (!reqs.contains(request.cmd)) {
            mcfish.http_response(res, 200, 'ret=-1&msg=invalid cmd\n');
            return;
        }
        // 向设备转发消息
        var sess = pool[request.sno];
        if (sess == null) {
            mcfish.http_response(res, 200, 'ret=-1&msg=invalid session\n');
            return;
        }
        if (request.sno.startsWith('WS')) {
            send_msg_woshi(request, sess);
            mcfish.http_response(res, 200, 'ret=0&msg=succ');
            return;
        }
        // 发送请求
        mcfish.http_response(res, 200, 'ret=0&msg=succ');

    });
});
HttpServer.listen(8180);
logger.info('-- http server is running : 8180 ... ');

/**************************************************************
 * TcpServer
 **************************************************************/
// Commands supported by the server
var cmds = ['register', 'init', 'heart', 'borrow', 'return', 'open', 'check', 'close'];

var TcpServer = net.createServer();
TcpServer.on('connection', function (socket) {
    logger.info('new connent: ' + socket.remoteAddress + ':' + socket.remotePort);
    socket.setKeepAlive(true, 80000);
    socket.on('data', function (data) {
        try {
            utils.parse(data, socket, dispatchRequest)
        } catch (error) {
            logger.error("[ req ] dev message parse error:" + error)
        }
    });
    socket.on('close', function (data) {
        logger.info('[ dev ] close dev :' + socket.remoteAddress + ':' + socket.remotePort);
        if (socket.sno != undefined) {
            // todo update powerbank station offline
            logger.info('[ dev ] Offline device number :' + socket.sno + " ； IP ：" + socket.remoteAddress + ' PORT:' + socket.remotePort);
            var sess = pool[socket.sno];
            if (sess != null) {
                sess.auth = null;
            }
        }
    });
    socket.on('error', function (data) {
        logger.error('[ socket ] error data :' + data);
    });
});

TcpServer.listen(8188);
logger.info('-- tcp server is running : 8188 ... ');

/**************************************************************
 * 业务逻辑处理 - 沃诗
 **************************************************************/
function dispatchRequest(socket, request) {

    switch (request.cmd) {
        case 0x60:    // 设备->服务器: 注册
            // 检查设备传递过来的参数是否合法
            if (request.sno == undefined) {
                logger.error("[ dev ] register parameter err, miss sno");
                return;
            }
            //todo init machine : update staus online, if machine not exist ,create a new machine ...

            mcfish.send_device_tcp_woshi(socket, '00086001001122334401');

            mcfish.send_device_tcp_woshi(socket, '000764010011223344');

            break;
        case 0x61:  // heartbeat
            //todo Update machine heartbeat time
            mcfish.send_device_tcp_woshi(socket, '000761010011223344');
            break;
        case 0x64:  // machine upload battery status
            do_cmd_detail_woshi(socket, request);
            //todo update battery status
            break;
        case 0x65:  // rent
            //todo update battery status & order status
            break;
        case 0x66:  // return powerbank
            //todo update battery status & order status

            mcfish.send_device_tcp_woshi(socket, '000966010111223344' + utils.PrefixInteger(request.position, 2) + '01');
            break;
        case 0x80:  // popup a powerbank
            //todo update battery status & order status
            break;
        default:
            logger.error('unknow cmd from dev:' + request.cmd);
            break;
    }
}

function do_cmd_detail_woshi(socket, request) {
    // 检查设备传递过来的参数是否合法
    if (request.sno == undefined || request.dnolist == undefined) {
        logger.info('[ dev ] return invalid: miss sno/dnolist');
        return;
    }
    let data = request.dnolist;
    for (let i = 0; i < data.length / 10; i++) {
        request.dno = utils.getBatteryId(data.slice(i * 10 + 1, i * 10 + 9));
        request.position = data[i * 10];
        request.bc = data[i * 10 + 9] * 20 + 20;
        //调用return_device函数

        //todo update battery status in database
    }


}

function send_msg_woshi(request, sess) {
    // 数据处理
    switch (request.cmd) {
        case 'borrow' ://已测试
            mcfish.send_device_tcp(sess.socket, Buffer.from([0x00, 0x08, 0x65, 0x01, 0x33, 0x11, 0x22, 0x33, 0x44, request.position]));
            break;
        case 'restart':
            mcfish.send_device_tcp(sess.socket, Buffer.from([0x00, 0x07, 0x64, 0x01, 0x33, 0x11, 0x22, 0x33, 0x44]));
            break;
        case 'close':
            mcfish.send_device_tcp(sess.socket, Buffer.from([0x00, 0x07, 0x64, 0x01, 0x33, 0x11, 0x22, 0x33, 0x44]));
            break;
        case 'version':
            mcfish.send_device_tcp(sess.socket, Buffer.from([0x00, 0x07, 0x64, 0x01, 0x33, 0x11, 0x22, 0x33, 0x44]));
            break;
        case 'open'://已测试
            mcfish.send_device_tcp(sess.socket, Buffer.from([0x00, 0x08, 0x80, 0x01, 0x33, 0x11, 0x22, 0x33, 0x44, request.position]));
            break;
        case 'setting'://机器迁移到其他服务器
            //ip:47.91.254.39  port:8188
            //003063010311223344000D34372E39312E3235342E333900000538313838001E
            //ip:119.23.69.149  port:8188
            //003163015711223344000E3131392E32332E36392E31343900000538313838001E
            mcfish.send_device_tcp_woshi(sess.socket, '003163015711223344000E3131392E32332E36392E31343900000538313838001E');
            break;
        default:
            break;
    }
}
